package nl.hva.three2learn.controller;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import javax.servlet.http.HttpSession;

import nl.hva.three2learn.authentication.Role;
import nl.hva.three2learn.authentication.UserAuthentication;
import nl.hva.three2learn.dao.ChapterDao;
import nl.hva.three2learn.dao.AnswerDao;
import nl.hva.three2learn.dao.CourseDao;
import nl.hva.three2learn.dao.ProgressTestDao;
import nl.hva.three2learn.dao.QuestionDao;
import nl.hva.three2learn.exception.ResourceNotFoundException;
import nl.hva.three2learn.model.Answer;
import nl.hva.three2learn.model.Chapter;
import nl.hva.three2learn.model.Course;
import nl.hva.three2learn.model.ProgressTest;
import nl.hva.three2learn.model.Question;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping("/progress_test")
public class ProgresstestController extends BaseController {
	
	@Autowired
	private ProgressTestDao progresstestDao;
	
	@Autowired
	private AnswerDao answerDao;
	
	@Autowired
	private QuestionDao questionDao;
	
	@Autowired
	private CourseDao courseDao;
	
	@Autowired
	private ChapterDao chapterDao;
	
	@Autowired
	private MessageSource messageSource;
	
	public boolean isTeacher(UserAuthentication ua) {
		return ua.getAuthorities().contains(Role.TEACHER.toString());
	}
	
	public boolean containsChapter(Chapter chapter, List<Chapter> chapters) {
		for(Chapter c: chapters) {
			if(c != null) {
				if(chapter.getId() == c.getId()) return true;
			}
		}
		return false;
	}
	
	@RequestMapping(value = "/{courseId}/{chapterId}/create", method = RequestMethod.GET)
	public String create(UserAuthentication userAuthentication, Locale locale, Model model,
			@PathVariable("courseId") long courseId, @PathVariable("chapterId") long chapterId) {
		
		Course course = courseDao.findById(courseId);
		Chapter chapter = chapterDao.findById(chapterId);
		ProgressTest progressTest = chapter.getProgressTest();
		
		if (progressTest != null) 
			return "redirect:/progress_test/edit_test/" + progressTest.getId() + "/";
		
		List<Chapter> chapters = course.getChapters();
		
		// Can't create test to course if it doesn't exist or if the chapter does not exist
		if ((course == null || chapter == null || !containsChapter(chapter, chapters)) && isTeacher(userAuthentication))
			throw new ResourceNotFoundException();

		model.addAttribute("title", messageSource.getMessage("progresstest.title", null, locale));
		model.addAttribute("courseId", courseId);
		model.addAttribute("chapterId", chapterId);
		
		return "course/progress_test/create";
	}
	
	@RequestMapping(value = "{courseId}/{chapterId}/testcreated", method = RequestMethod.POST)
	public String testcreated(UserAuthentication userAuthentication, Locale locale,
			@PathVariable("courseId") long courseId, @PathVariable("chapterId") long chapterId,
			@RequestParam("description") String description) {

		Course course = courseDao.findById(courseId);
		List<Chapter> chapters = course.getChapters();
		Chapter chapter = chapterDao.findById(chapterId);

		// Can't create test to course if it doesn't exist or if the chapter does not exist
		if ((course == null || chapter == null || !containsChapter(chapter, chapters)) && isTeacher(userAuthentication))
			throw new ResourceNotFoundException();
		
		ProgressTest pt = new ProgressTest(description);
		progresstestDao.save(pt);
		
		chapter.setProgressTest(pt);
		chapterDao.save(chapter);
		
		return "redirect:/progress_test/edit_test/" + pt.getId() + "/";
	}
	
	@RequestMapping(value = "/edit_test/{testId}/edit", method = RequestMethod.POST)
	public String edit(@PathVariable("testId") long testId,
			@RequestParam("description") String description) {
		
		ProgressTest pt = progresstestDao.findById(testId);
		
		if(pt == null)
			throw new ResourceNotFoundException();
		
		pt.setDescription(description);
		progresstestDao.save(pt);
		
		return "redirect:/progress_test/edit_test/" + testId + "/";
	}
	
	@RequestMapping(value = "/edit_test/{testId}")
	public ModelAndView editTest(HttpSession session, Locale locale,
			@PathVariable("testId") long testId) {
		
		ProgressTest pt = progresstestDao.findById(testId);
		
		if(pt == null) throw new ResourceNotFoundException();
		
		ModelAndView modelAndView = new ModelAndView("course/progress_test/edit");
		modelAndView.addObject("ProgressTest", pt);
		
		if(pt.getQuestions() == null) pt.setQuestionS(new ArrayList<Question>());
		modelAndView.addObject("Questions", pt.getQuestions());
		
		return modelAndView;
	}
	
	@RequestMapping(value = "/edit_test/{testId}/create_question")
	public ModelAndView createQuestion(HttpSession session, Locale locale,
			@PathVariable("testId") long testId) {
		
		ProgressTest pt = progresstestDao.findById(testId);
		
		if(pt == null) throw new ResourceNotFoundException();
		
		ModelAndView modelAndView = new ModelAndView("course/progress_test/create_question");
		modelAndView.addObject(pt);
		
		return modelAndView;
	}
	
	@RequestMapping(value = "/edit_test/{testId}/add_question", method = RequestMethod.POST)
	public String addQuestion(HttpSession session,
			@PathVariable("testId") long testId,
			@RequestParam("question") String question,
			@RequestParam("answerA") String answerA,
			@RequestParam("answerB") String answerB,
			@RequestParam("answerC") String answerC,
			@RequestParam("answerD") String answerD,
			@RequestParam("rightAnswer") String rightAnswer) {
		
		ProgressTest pt = progresstestDao.findById(testId);
		
		if(pt == null) {
			System.out.println("Not found");
			throw new ResourceNotFoundException();
		}
		
		List<Answer> answers = new ArrayList<Answer>();
		Answer a = new Answer(answerA);
		answerDao.save(a);
		answers.add(a);
		
		Answer b = new Answer(answerB);
		answerDao.save(b);
		answers.add(b);
		
		Answer c = new Answer(answerC);
		answerDao.save(c);
		answers.add(c);
		
		Answer d = new Answer(answerD);
		answerDao.save(d);
		answers.add(d);
		
		Question q = new Question(question, answers, rightAnswer, true);
		questionDao.save(q);
		
		List<Question> questions;
		if(pt.getQuestions() == null) questions = new ArrayList<Question>();
		else questions = pt.getQuestions();
		questions.add(q);
		pt.setQuestionS(questions);
		progresstestDao.save(pt);
		
		return "redirect:/progress_test/edit_test/" + testId + "/";
	}
	
	@RequestMapping(value = "/edit_test/{testId}/remove_question/{questionId}")
	public String removeQuestion(@PathVariable("testId") long testId,
			@PathVariable("questionId") long questionId) {
		
		Question question = questionDao.findById(questionId);
		
		if(question == null)
			throw new ResourceNotFoundException();
		
		questionDao.remove(question);
		return "redirect:/progress_test/edit_test/" + testId + "/";
	}
	
	@RequestMapping(value = "/do_test/{testId}")
	public String startTest(HttpSession session,
			@PathVariable("testId") long testId) {
		
		if(session.getAttribute("answersOnTest") != null) session.removeAttribute("answersOnTest");
		session.setAttribute("answersOnTest", new ArrayList<String>());
		
		return "redirect:/progress_test/do_test/" + testId + "/1";
	}
	
	@RequestMapping(value = "/do_test/{testId}/{curQuestion}", method = RequestMethod.POST)
	public ModelAndView doTest(HttpSession session,
			@PathVariable("testId") long testId,
			@PathVariable("curQuestion") int curQuestion,
			@RequestParam("answer") String answer,
			@RequestParam("answeredQuestion") int answeredQuestion) {
		ProgressTest pt = progresstestDao.findById(testId);
		
		if(pt == null)
			throw new ResourceNotFoundException();
		
		List<Question> questions = pt.getQuestions();
		List<String> answers = (List<String>) session.getAttribute("answersOnTest");
		
		if(answeredQuestion == 
				((int) answers.size()+1)
				&& answeredQuestion <= questions.size())
			answers.add(answer);
		else if(answeredQuestion < questions.size()) answers.set(((int) answeredQuestion-1), answer);
		
		ModelAndView modelAndView = new ModelAndView("course/progress_test/do_test");
		
		boolean done;
		if(curQuestion == (int) pt.getQuestions().size() + 1) {
			done = true;
			
			int right = 0;
			for(int i = 0; i < answers.size(); i++) {
				if(questions.get(i) != null && questions.get(i).getAnswer().equalsIgnoreCase(answers.get(i))) {
					right++;
					answers.set(i, "<right>" + answers.get(i) + "</right>");
				} else if(answers.get(i) != null) answers.set(i, "<wrong>" + answers.get(i) + "</wrong>");
			}
			
			double mark = ((double) right / (double) questions.size()) * 10d;
			DecimalFormat df = new DecimalFormat("##0.00");
			
			modelAndView.addObject("mark", df.format(mark));
			modelAndView.addObject("right", right);
			modelAndView.addObject("total", questions.size());
			modelAndView.addObject("answers", answers);
		} else {
			if(curQuestion < 1) curQuestion = 1;
			else if(curQuestion > pt.getQuestions().size())curQuestion = pt.getQuestions().size();
			
			session.removeAttribute("answersOnTest");
			session.setAttribute("answersOnTest", answers);
			
			Question question = questions.get(curQuestion-1);
			List<Answer> possibleAnswers = question.getAnswers();
			
			char[] answerChars = new char[possibleAnswers.size()];
			int i = 0;
			for (char c = 'A'; i < answerChars.length; c++)
				answerChars[i++] = c;
			
			modelAndView.addObject("answerChars", answerChars);
			
			done = false;
			modelAndView.addObject("curQuestion", curQuestion);
			modelAndView.addObject("question", question.getQuestion());
			modelAndView.addObject("possibleAnswers", possibleAnswers);
		}
		
		modelAndView.addObject("done", done);
		
		return modelAndView;
	}
	
	@RequestMapping(value = "/do_test/{testId}/{curQuestion}", method = RequestMethod.GET)
	public ModelAndView doTest(HttpSession session,
			@PathVariable("testId") long testId,
			@PathVariable("curQuestion") int curQuestion) {
		ProgressTest pt = progresstestDao.findById(testId);
		
		if(pt == null)
			throw new ResourceNotFoundException();
		
		if(curQuestion < 1) curQuestion = 1;
		else if(curQuestion > pt.getQuestions().size())curQuestion = pt.getQuestions().size();
		
		Question q = pt.getQuestions().get(curQuestion-1);
		List<Answer> possibleAnswers = q.getAnswers();
		
		ModelAndView modelAndView = new ModelAndView("course/progress_test/do_test");
		modelAndView.addObject("curQuestion", curQuestion);
		modelAndView.addObject("question", q.getQuestion());
		modelAndView.addObject("possibleAnswers", possibleAnswers);
		
		char[] answerChars = new char[possibleAnswers.size()];
		int i = 0;
		for (char c = 'A'; i < answerChars.length; c++)
			answerChars[i++] = c;
		
		modelAndView.addObject("answerChars", answerChars);
		modelAndView.addObject("done", false);
		
		return modelAndView;
	}
}
